package spider

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"gdei_healthy_colly/log"
	"github.com/PuerkitoBio/goquery"
	"go.uber.org/zap"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

// 解析每日表单
func parseDailyForm(reader io.Reader) (values *url.Values, err error) {
	// goQuery解析页面
	doc, err := goquery.NewDocumentFromReader(reader)
	if err != nil {
		return
	}

	// 初始化变量
	values = &url.Values{}

	// #form-mrcj-add input
	doc.Find("#form-mrcj-add input[name!='']").Each(func(i int, s *goquery.Selection) {
		key, isExist := s.Attr("name")
		if !isExist {
			return
		}

		value, isExist := s.Attr("value")
		if !isExist || strings.Contains(value, "不适") {
			return
		}

		// 追加
		values.Set(key, value)
	})
	return
}

// 获取每日表单
func getDailyForm(ctx context.Context, client *http.Client) (values *url.Values, err error) {
	// 构造Request请求
	op := opMapper[opDailyFormGet]
	req, err := http.NewRequestWithContext(ctx, op.Method, op.Url(), nil)
	if err != nil {
		return
	}
	req.Header.Set("User-Agent", UserAgent)
	req.Header.Set("Referer", Referer)

	// 判断是否拥有Cookies
	if client.Jar.Cookies(req.URL) == nil {
		return values, LoginRequiredErr
	}

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	respData, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	if resp.StatusCode != http.StatusOK {
		return values, fmt.Errorf("response status not ok: %v", string(respData))
	}

	// 登陆检测，发现跳转
	if resp.Request.Response != nil && (resp.Request.Response.StatusCode == http.StatusFound || resp.Request.URL.String() == opMapper[opLogin].Url()) {
		return values, LoginRequiredErr
	}

	return parseDailyForm(bytes.NewReader(respData))
}

// 提交每天表单
func dailyFormPost(ctx context.Context, ac Account, opKey uint, values *url.Values) (err error) {
	// 20201023 如果是修改的情况则记录日志并跳出
	if opKey == opDailyFormEdit {
		log.Logger.Info("[提交表单]发生修改操作，已跳过", zap.String("用户名", ac.GetUsername()))
		return
	}

	if values == nil {
		return fmt.Errorf("参数为空")
	}

	// 加上学号
	if strings.EqualFold(values.Get("xh"), "") {
		values.Set("xh", ac.GetId())
	}

	// 防止体温为0
	if strings.EqualFold(values.Get("tiwen"), "") {
		values.Set("tiwen", randTemperature())
	}

	// 根据传入的opKey做不同的操作
	op := opMapper[opKey]

	req, err := http.NewRequestWithContext(ctx, op.Method, op.Url(), strings.NewReader(values.Encode()))
	if err != nil {
		return
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("User-Agent", UserAgent)

	resp, err := ac.GetClient().Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	respData, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	r := new(respStruct)
	if err = json.Unmarshal(respData, r); err != nil {
		return
	}
	if r.Code != 0 {
		return fmt.Errorf("%v", *r)
	}
	return
}
